#ifndef GLOBALOBJ_H
#define GLOBALOBJ_H
#include "global_object.h"
#include "cuda_runtime.h"
#include <cstdlib>


template <class T>
class GlobalObj
{
public:

	T data_h;
	T* data_d;

	inline __host__ GlobalObj(){
		cudaMalloc<T>(&this->data_d, sizeof(T));
		setData(T());
	}

	inline __host__ GlobalObj(T& init){
		cudaMalloc<T>(&this->data_d, sizeof(T));
		setData(init);
	}

	inline __host__ ~GlobalObj(){
		cudaFree(data_d);
	}

	inline __host__ void updateDevice() {
			//copy this data to the device
			cudaMemcpy(this->data_d, &data_h, sizeof(T), cudaMemcpyHostToDevice); 
	}

	inline __host__ void getFromDevice(){
		cudaMemcpy(&data_h, data_d, sizeof(T), cudaMemcpyDeviceToHost); 
	}

	inline __host__ __device__  T& operator=(T& rhs){
		setData(rhs);
		return getData();
	}

	inline __host__ __device__  GlobalObj<T>& operator=(GlobalObj<T>& rhs){
		setData(rhs);
		return *this;
	}

	inline __host__ __device__  T& operator->() {
		return getData();
	}

	inline __host__ void setData(T& data){
		#ifdef __CUDA_ARCH__
			memcpy(data_d, &data, sizeof(T));
		#else
			data_h = data;
			updateDevice();
		#endif
	}

	inline __host__ __device__  T& getData() {
		#ifdef __CUDA_ARCH__
			return *data_d;
		#else
			return data_h;
		#endif
	}

};

#endif
